package orgInfo

// 用于组织创建 上下文、客户端、获取peer实例
import (
	"fabric-go-sdk/tools"
	"fmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
	mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)

// GetClientProvider 为管理员用户获取ClientProvider
func (o *OrgInfo) GetClientProvider(fabSDK *fabsdk.FabricSDK, userName string) (clientProvider *contextAPI.ClientProvider, err error) {
	// 检查用户是否是该组织的管理员
	if !(userName == o.AdminUser) {
		err := fmt.Errorf("GetClientProvider error:用户%v不为管理员", userName)
		return nil, err
	}
	context := fabSDK.Context(fabsdk.WithUser(userName), fabsdk.WithOrg(o.OrgName))
	return &context, nil
}

// CreatMSPClient 创建管理员MSP客户端 用于组织的Msp管理
func (o *OrgInfo) CreatMSPClient(fabSDK *fabsdk.FabricSDK, userName string) (mspClient *mspclient.Client, err error) {
	// 获取context
	cliContext, err := o.GetClientProvider(fabSDK, userName)
	if err != nil {
		fmt.Errorf("CreatMSPClient err:%v", err)
		return nil, err
	}
	// 创建客户端
	mspClient, err = mspclient.New(*cliContext)
	if err != nil {
		fmt.Errorf("CreatMSPClient err:%v", err)
		return nil, err
	}
	return mspClient, nil
}

// CreatResmgmt 创建管理员资源管理客户端  用于链码生命周期
func (o *OrgInfo) CreatResmgmt(fabSDK *fabsdk.FabricSDK, userName string) (resmgmtClient *resmgmt.Client, err error) {
	// 获取context
	cliContext, err := o.GetClientProvider(fabSDK, userName)
	if err != nil {
		fmt.Errorf("CreatResmgmt err:%v", err)
		return nil, err
	}
	// 创建客户端
	resmgmtClient, err = resmgmt.New(*cliContext)
	if err != nil {
		fmt.Errorf("CreatResmgmt err:%v", err)
		return nil, err
	}
	return resmgmtClient, nil
}

// GetPeers 获取该组织所有Peer节点
func (o *OrgInfo) GetPeers(fabSDK *fabsdk.FabricSDK) (peers []fab.Peer, err error) {
	context, _ := o.GetClientProvider(fabSDK, o.AdminUser)
	peers, err = tools.DiscoverLocalPeers(*context, len(o.PeersUrl))
	if err != nil {
		err := fmt.Errorf("DiscoverLocalPeers error: %v", err)
		return nil, err
	}
	return peers, nil
}

// GetPeerByUrl 获取指定节点
func (o *OrgInfo) GetPeerByUrl(fabSDK *fabsdk.FabricSDK, peerUrl string) (peer fab.Peer, err error) {
	context, _ := o.GetClientProvider(fabSDK, o.AdminUser)
	peers, err := tools.DiscoverLocalPeers(*context, len(o.PeersUrl))
	if err != nil {
		err := fmt.Errorf("DiscoverLocalPeers error: %v", err)
		return nil, err
	}
	// 遍历peers找到指定的peer
	for _, peer := range peers {
		fmt.Println("=== GetPeerByUrl peer url=== ", peer.URL())
		if peer.URL() == peerUrl {
			return peer, nil
		}
	}
	return nil, fmt.Errorf("GetPeerByUrl err:在组织%v中不存在节点%v", o.OrgName, peerUrl)
}

// GetChannelProvider 为普通用户获取ChannelProvider
func (o *OrgInfo) GetChannelProvider(fabSDK *fabsdk.FabricSDK, channelId string, userName string) (channelProvider *contextAPI.ChannelProvider, err error) {
	// 检查用户是否是该组织的管理员
	if !(tools.ElementInSlice(userName, o.NormalUsers)) {
		err := fmt.Errorf("GetChannelProvider error:用户%v不在%v组织中", userName, o.OrgName)
		return nil, err
	}
	channelContext := fabSDK.ChannelContext(channelId, fabsdk.WithUser(userName), fabsdk.WithOrg(o.OrgName))
	return &channelContext, nil
}

// CreatChannelClient 普通用户创建通道客户端 用于调用链码等
func (o *OrgInfo) CreatChannelClient(fabSDK *fabsdk.FabricSDK, channelId string, userName string) (chClient *channel.Client, err error) {
	// 获取context
	chContext, err := o.GetChannelProvider(fabSDK, channelId, userName)
	if err != nil {
		fmt.Errorf("CreatChannelClient err:%v", err)
		return nil, err
	}
	// 创建通道客户端
	chClient, err = channel.New(*chContext)
	if err != nil {
		fmt.Errorf("CreatChannelClient err:%v", err)
		return nil, err
	}
	return chClient, nil
}

// CreatLedgerClient 普通用户创建通道客户端 用于账本底层查询操作 eg：根据id查询block
func (o *OrgInfo) CreatLedgerClient(fabSDK *fabsdk.FabricSDK, channelId string, userName string) (leClient *ledger.Client, err error) {
	// 获取context
	chContext, err := o.GetChannelProvider(fabSDK, channelId, userName)
	if err != nil {
		fmt.Errorf("CreatChannelClient err:%v", err)
		return nil, err
	}
	// 创建通道客户端
	leClient, err = ledger.New(*chContext)
	if err != nil {
		fmt.Errorf("CreatChannelClient err:%v", err)
		return nil, err
	}
	return leClient, nil
}
